package com.mf.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mf.annotation.SearchAnnotation;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: lmf
 * @Create: 2024/7/11 10:23
 * Description:
 */
public class MybatisPlusUtils {
    /**
     * 生成查询条件
     */
    public static <T, V> QueryWrapper<V> getQueryWrapper(T params, Class<V> clazz) {
        QueryWrapper<V> queryWrapper = new QueryWrapper<>();
        // 假设T和V的字段名是一致的
        for (Field field : params.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            try {
                Object fieldValue = field.get(params);
                if (VerifyUtils.isNotEmpty(fieldValue)) {
                    setParams(queryWrapper, field, fieldValue);
                }
            } catch (IllegalAccessException e) {
                // 异常处理...
                throw new RuntimeException(e);
            }
        }
        return queryWrapper;
    }

    /**
     * 设置查询参数
     */
    private static <V> void setParams(QueryWrapper<V> queryWrapper, Field field, Object fieldValue) {
        SearchAnnotation searchAnnotation = field.getAnnotation(SearchAnnotation.class);
        if (searchAnnotation != null) {
            String value = searchAnnotation.value();

            if ("eq".equals(value) && VerifyUtils.isNotEmpty(value)) {
                // 注意这里我们使用key作为V类型的字段名
                queryWrapper.eq(CommonUtils.toUnderScoreCase(field.getName()), fieldValue); // 可能需要类型转换或确保fieldValue与V类型兼容
            }
            // 设置模糊查询字段
            setLikeKey(queryWrapper, fieldValue, searchAnnotation);
        }
    }

    /**
     * 设置模糊查询字段 【key】
     */
    private static <V> void setLikeKey(QueryWrapper<V> queryWrapper, Object fieldValue,
                                       SearchAnnotation searchAnnotation) {
        String key = searchAnnotation.key();
        // 假设key就是字段名，因为T和V的字段名一致
        if (VerifyUtils.isNotEmpty(key)) {
            String[] keys = key.split(",");
            queryWrapper.and(wrapper -> {
                boolean first = true;
                for (String k : keys) {
                    if (first) {
                        wrapper.like(k, fieldValue); // 同样可能需要类型转换
                        first = false;
                    } else {
                        wrapper.or().like(k, fieldValue);
                    }
                }
            });
        }
    }


    /**
     * 修改分页数据类型
     */
    public static <T, V> Page<V> changePageDataClass(Page<T> originPage, Class<V> newClass) {
        List<V> collect = originPage.getRecords().stream()
                .map(bo -> {
                    V v = null;
                    // 通过反射 创建新对象
                    try {
                        v = newClass.getDeclaredConstructor().newInstance();
                        BeanUtils.copyProperties(bo, v);
                    } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                             NoSuchMethodException e) {
                        throw new RuntimeException(e);
                    }
                    return v;
                }).toList();
        return new Page<V>(originPage.getCurrent(), originPage.getSize(), originPage.getTotal()).setRecords(collect);
    }

    /**
     * 修改数据类型
     */
    public static <T, V> List<V> changeDataClass(List<T> originList, Class<V> newClass) {
        return changeDataClass(originList, newClass, t -> {
        });
    }

    @FunctionalInterface
    public interface BiConsumerWithVoid<T> {
        void accept(T t);
    }

    /**
     * 修改数据类型
     */
    public static <T, V> List<V> changeDataClass(List<T> originList, Class<V> newClass, BiConsumerWithVoid<T> mapper) {
        V v = null;
        try {
            ArrayList<V> vArrayList = new ArrayList<>();
            for (T t : originList) {
                v = newClass.getDeclaredConstructor().newInstance();
                mapper.accept(t);
                BeanUtils.copyProperties(t, v);
                vArrayList.add(v);
            }
            return vArrayList;

        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }


}
